package com.yonyougov.devops.cruxcisupport.appenv;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.yonyougov.devops.cruxcisupport.app.AppService;
import com.yonyougov.devops.cruxcisupport.appenv.dto.*;
import com.yonyougov.devops.cruxcisupport.appenv.vo.AppEnvPageLikeReqVo;
import com.yonyougov.devops.cruxcisupport.appenv.vo.AppEnvPageLikeRespVo;
import com.yonyougov.devops.cruxcisupport.component.RhTask;
import com.yonyougov.devops.cruxcisupport.component.UserStore;
import com.yonyougov.devops.cruxcisupport.envversionhistory.EnvVersionHistoryService;
import com.yonyougov.devops.cruxcisupport.k8s.K8sTask;
import com.yonyougov.devops.cruxcisupport.thread.HandleEnvVersionHistoryThread;
import com.yonyougov.devops.cruxcisupport.version.VersionService;
import com.yonyougov.devops.fwc.api.dto.BaseResponseDto;
import com.yonyougov.devops.fwc.core.controller.CrudController;
import com.yonyougov.devops.fwc.core.service.BaseService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.SneakyThrows;
import org.springframework.beans.BeanUtils;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import java.math.BigInteger;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.*;

/**
 * Created by ligson on 2017/8/11.
 */
@Api(tags = "环境应用模块")
@RestController
@RequestMapping("/api/v2/appenv")
public class AppEnvController extends CrudController<AppEnvEntity, BigInteger> {

    private final AppEnvService appEnvService;
    private final RhTask rhTask;
    private final K8sTask k8sTask;
    private final ObjectMapper objectMapper;
    private final VersionService versionService;
    private final AppService appService;
    private final UserStore userStore;
    private final EnvVersionHistoryService envVersionHistoryService;

    public AppEnvController(AppEnvService appEnvService, ObjectMapper objectMapper, RhTask rhTask, VersionService versionService, UserStore userStore, EnvVersionHistoryService envVersionHistoryService, AppService appService, K8sTask k8sTask) {
        this.appEnvService = appEnvService;
        this.objectMapper = objectMapper;
        this.rhTask = rhTask;
        this.versionService = versionService;
        this.userStore = userStore;
        this.envVersionHistoryService = envVersionHistoryService;
        this.appService = appService;
        this.k8sTask = k8sTask;
    }

    @Override
    public BaseService<AppEnvEntity, BigInteger> getService() {
        return appEnvService;
    }

    //<!--用户自定义代码开始-->

    @ApiOperation(value = "前端部署信息新增调用", notes = "部署信息新增")
    @PostMapping(value = "/ae/add")
    @SneakyThrows
    public BaseResponseDto addAppEnv(@RequestBody @Valid AppEnvAddRequestDto requestDto) {
        AppEnvEntity appEnvEntity = new AppEnvEntity();
        BeanUtils.copyProperties(requestDto, appEnvEntity);
        appEnvService.add(appEnvEntity);
        HandleEnvVersionHistoryThread handleEnvVersionHistoryThread =
                new HandleEnvVersionHistoryThread(Arrays.asList(appEnvEntity), versionService, userStore, envVersionHistoryService, appService);
        handleEnvVersionHistoryThread.start();
        return BaseResponseDto.getSuccessInstance();
    }

    @ApiOperation(value = "前端部署信息修改调用", notes = "部署信息修改")
    @PostMapping(value = "/ae/update")
    @SneakyThrows
    public BaseResponseDto updateAppEnv(@RequestBody @Valid AppEnvUpdateRequestDto requestDto) {
        AppEnvEntity appEnvEntity = new AppEnvEntity();
        BeanUtils.copyProperties(requestDto, appEnvEntity);
        appEnvService.updateAppEnv(appEnvEntity);
        return BaseResponseDto.getSuccessInstance();
    }

    @ApiOperation(value = "前端部署信息列表展示调用", notes = "可选择根据应用名称进行模糊查询，根据当前用户的角色查询部署信息")
    @SneakyThrows
    @PostMapping(value = "/ae/page/like")
    public BaseResponseDto findAppEnvLikePage(@RequestBody AppEnvPageLikeRequestDto requestDto) {
        AppEnvPageLikeDbParams dbParams = new AppEnvPageLikeDbParams();
        BeanUtils.copyProperties(requestDto, dbParams);
        return appEnvService.findAppEnvLikePage(dbParams);
    }

    @PostMapping(value = "/ae/delete/id")
    @SneakyThrows
    public BaseResponseDto deleteAppEnvById(@RequestBody @Valid AppEnvDeleteRequestDto requestDto) {
        AppEnvEntity appEnvEntity = new AppEnvEntity();
        appEnvEntity.setId(requestDto.getId());
        appEnvService.deleteAppEnvWithAppendages(appEnvEntity);
        return BaseResponseDto.getSuccessInstance();
    }

    @PostMapping(value = "/ae/batchdelete")
    @SneakyThrows
    public BaseResponseDto batchdelete(@RequestBody @Valid AppEnvBatchDeleteRequestDto requestDto) {
        AppEnvBatchDeleteDto appEnvBatchDeleteDto = new AppEnvBatchDeleteDto();
        BeanUtils.copyProperties(requestDto, appEnvBatchDeleteDto);
        appEnvService.batchDeleteAppEnvWithAppendages(appEnvBatchDeleteDto);
        return BaseResponseDto.getSuccessInstance();
    }

    @PostMapping("/ae/syncstate")
    @SneakyThrows
    public boolean syncstate(@RequestBody String requestBody) {
        String envName = objectMapper.readTree(requestBody).get("envName").asText();
        k8sTask.syncPodStatus(envName);
//        rhTask.sync(envName);
        return true;
    }


    @ApiOperation(value = "前端获取实时版本信息调用", notes = "获取某个环境下应用的实时版本")
    @PostMapping("/ae/versionInfo")
    @SneakyThrows
    public String getAppVersionInfo(@RequestBody String requestBody) {
        String envName = objectMapper.readTree(requestBody).get("envName").asText();
        return appEnvService.getAppVersionByEnv(envName);
    }

    @PostMapping("/ae/syncdata")
    @SneakyThrows
    public boolean syncData(@RequestBody String requestBody) {
        String sourceEnv = objectMapper.readTree(requestBody).get("sourceEnv").asText();
        String targetEnv = objectMapper.readTree(requestBody).get("targetEnv").asText();
        return appEnvService.syncData(sourceEnv, targetEnv);
    }

    @ApiOperation(value = "后台内部调用", notes = "根据应用名字和环境名字模糊分页查")
    @PostMapping("/ae/page/like/envname/appname")
    @SneakyThrows
    public BaseResponseDto findPageLike(@RequestBody @Valid AppEnvPageLikeReqDto request) {
        AppEnvPageLikeReqVo appEnvPageLikeReqVo = new AppEnvPageLikeReqVo();
        BeanUtils.copyProperties(request, appEnvPageLikeReqVo);
        List<AppEnvPageLikeRespVo> datas = appEnvService.findPageLike(appEnvPageLikeReqVo);
        int totalCount = appEnvService.countByPageLike(appEnvPageLikeReqVo);
        BaseResponseDto result = BaseResponseDto.getSuccessInstance();
        result.put("totalCount", totalCount);
        result.put("data", datas);
        return result;
    }

    @PostMapping("/ae/versioninit")
    @SneakyThrows
    public BaseResponseDto versionInit(@RequestBody @Valid VersionInitRequestDto request) {
        VersionInitDto versionInitDto = new VersionInitDto();
        BeanUtils.copyProperties(request, versionInitDto);
        appEnvService.versionInit(versionInitDto);
        return BaseResponseDto.getSuccessInstance();
    }

    /**
     * 打印某个环境下所有的端口映射
     * @return
     */
    @GetMapping("/ae/portreport/{env}")
    public BaseResponseDto portReport(@PathVariable("env") String env) {
        List<PortBillResponseDto> data = appEnvService.printPortReport(env);
        BaseResponseDto successInstance = BaseResponseDto.getSuccessInstance();
        HashMap<String, Object> dataMap = new HashMap<>();
        dataMap.put("portbill",data);
        successInstance.setData(dataMap);
        return successInstance;
    }

    /**
     * 打印某个环境下所有的端口映射（yml）
     * @return
     */
    @GetMapping("/ae/portreport/{env}/_yml")
    public String portBillReport(@PathVariable("env") String env) {
        List<PortBillResponseDto> data = appEnvService.printPortReport(env);
        StringBuilder stringBuilder = new StringBuilder();
        stringBuilder.append("env:\n" +
                "  eureka:\n" +
                "    instance:\n");
        for (PortBillResponseDto datum : data) {
            for (HashMap<String, String> port : datum.getPorts()) {
                if(port.containsKey("http") || port.containsKey("tcp")){
                    String appName = datum.getAppName();
                    stringBuilder.append("      "+appName+":\n");
                    stringBuilder.append("        non-secure-port: "+port.get("http").split(" -> ")[1]+"\n");
                }

            }
        }
        return stringBuilder.toString();
    }

    /**
     * 打印某个环境下所有的版本
     * @return
     */
    @GetMapping("/ae/versionreport/{env}")
    public Object versionReport(@PathVariable("env") String env) {
        Map<String,String> data = appEnvService.printVersionReport(env);
        return data;
    }
    /**
     * 打印某个环境下所有的版本
     * @return
     */
    @GetMapping("/ae/versionreport/{env}/_text")
    public Object versionReportText(@PathVariable("env") String env) {
        Map<String,String> data = appEnvService.printVersionReport(env);
        StringBuilder stringBuilder = new StringBuilder();
        for (Map.Entry<String, String> entry : data.entrySet()) {
            stringBuilder.append(entry.getKey()+":"+entry.getValue()+"\n");
        }
        return stringBuilder;
    }
}
